#pragma once
#include <iostream>
#include <unistd.h>
#include <vector>
#include <semaphore.h>
#include <thread>
#include "Task.hpp"


using namespace std;

const static int defaultCap = 5;
template<class T>
class RingQueue
{
private://对PV操作进行封装
    void P(sem_t& sem)
    {
        sem_wait(&sem);
    }
    void V(sem_t& sem)
    {
        sem_post(&sem);
    }
    void Lock(pthread_mutex_t& mutex)
    {
        pthread_mutex_lock(&mutex);
    }
    void Unlock(pthread_mutex_t& mutex)
    {
        pthread_mutex_unlock(&mutex);
    }
public:
    RingQueue(int cap = defaultCap)
        :_ringQueue(cap)
        ,_cap(cap)
        ,c_step(0)
        ,p_step(0)
    {
        //信号量初始化：信号量本质是计数器
        sem_init(&c_data_sem, 0, 0);
        sem_init(&p_space_sem, 0, cap);
        pthread_mutex_init(&c_mutex,nullptr);
        pthread_mutex_init(&p_mutex,nullptr);
    }

    void Push(const T& in)
    {
        //product
        P(p_space_sem);
        Lock(p_mutex);
        _ringQueue[p_step] = in;
        p_step++;
        p_step %= _cap;//防止越界，维持环形队列特征
        Unlock(p_mutex);
        V(c_data_sem);
    }
    void Pop(T* out)
    {
        //consumer
        P(c_data_sem);
        Lock(c_mutex);
        *out = _ringQueue[c_step];
        c_step++;
        c_step %= _cap;
        Unlock(c_mutex);
        V(p_space_sem);

    }
    ~RingQueue()
    {
        sem_destroy(&c_data_sem);
        sem_destroy(&p_space_sem);
        pthread_mutex_destroy(c_mutex);
        pthread_mutex_destroy(p_mutex);
    }
private:
    vector<T> _ringQueue;//环形队列
    int _cap;//队列容量

    int c_step;//消费者位置
    int p_step;//生产者位置

    sem_t c_data_sem;//消费者关注的信号量：数据资源
    sem_t p_space_sem;//生产者关注的信号量：空间资源

    pthread_mutex_t c_mutex;
    pthread_mutex_t p_mutex;
};